package transformnumber

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"
)

// todo: 需要加一个 昨天/前天/昨日/前日/今天/今日/明天/明日/后天/后日/今年/去年/明年/前年/后年 的处理
// todo: 时间段的解析方式

// 处理时间中的小时情况
func (t *Transform) TransformChineseTimeofHour(inputs string) (string, int, error) {

	addDayFlag := 0 // 是否需要加一天, 为0表示不用添加
	// 处理时间, 需要处理包含一刻, 半, 整的状况
	patternTime := regexp.MustCompile(fmt.Sprintf(`[%s%s0-9]+\s*时\s*(半|一刻|整)`, t.allNum, t.allUnit))

	// 去掉空白字符
	inputs = removeSpace(inputs)

	result := patternTime.ReplaceAllStringFunc(inputs, func(s string) string {
		if strings.Contains(s, "时一刻") {
			s = strings.Replace(s, "时一刻", ":15:00", 1)
		} else if strings.Contains(s, "时半") {
			s = strings.Replace(s, "时半", ":30:00", 1)
		} else if strings.Contains(s, "时整") {
			s = strings.Replace(s, "时整", ":00:00", 1)
		}

		return t.subUtil(s, "cn2an", "date")
	})

	// 包含时分秒的情况
	patternTime2 := regexp.MustCompile(fmt.Sprintf(`[%s%s0-9]+\s*时(\s*[%s%s0-9]+\s*分(\s*[%s%s0-9]+\s*秒)?)?`, t.allNum, t.allUnit, t.allNum, t.allUnit, t.allNum, t.allUnit))
	result = patternTime2.ReplaceAllStringFunc(result, func(s string) string {
		// 去掉空白字符
		s = removeSpace(s)

		// 转换为数字
		s = t.subUtil(s, "cn2an", "date")
		if strings.Contains(s, "秒") {
			s = strings.NewReplacer("时", ":", "分", ":", "秒", "").Replace(s)
		} else if strings.Contains(s, "分") {
			s = strings.NewReplacer("时", ":", "分", ":00").Replace(s)
		} else if strings.Contains(s, "时") {
			s = strings.NewReplacer("时", ":00:00").Replace(s)
		}

		return s
	})

	result1, flag, _ := t.TransformChineseTimeofDaylight(result)
	// 处理时间, 返回时间的字符串前加一个空格
	regTime1 := regexp.MustCompile(`\s*[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\s*`)
	result1 = regTime1.ReplaceAllStringFunc(result1, func(s string) string {
		s = strings.TrimSpace(s)
		splitS := strings.Split(s, ":")
		switch flag {
		case 1: // 上午
			return " " + s
		case 2: // 下午
			hour, _ := strconv.Atoi(splitS[0])
			if hour < 12 {
				splitS[0] = strconv.Itoa(hour + 12)
			}
			return " " + strings.Join(splitS, ":")
		case 3: // 晚上
			hour, _ := strconv.Atoi(splitS[0])
			// 24小时制, 24点为0点, 夜晚的12点为0点
			if hour == 24 || hour == 12 {
				splitS[0] = "0"
				addDayFlag = 1
			}
			// 当我们说晚上1点到晚上5点的时候, 一般说的是前一天的日期, 所以需要加一天. 如果是凌晨1点到凌晨5点, 就是当天的日期, 不用加一天.
			if hour < 5 {
				addDayFlag = 1
			}
			// 当我们说晚上6点到晚上11点的时候, 指的是18点到23点
			if hour > 5 && hour < 12 {
				splitS[0] = strconv.Itoa(hour + 12)
			}
			return " " + strings.Join(splitS, ":")
		default:
			return " " + s
		}
	})

	return result1, addDayFlag, nil
}

// 处理早上/下午/晚上/凌晨/午夜/夜晚/晚/夜/夜间
func (t *Transform) TransformChineseTimeofDaylight(inputs string) (string, int, error) {
	flag := 0

	amReg := regexp.MustCompile(`(上午|早上|午前|早间|早晨|凌晨|清晨)`)
	pmReg := regexp.MustCompile(`(下午|傍晚|午后|黄昏)`)
	nightReg := regexp.MustCompile(`(午夜|晚上|夜晚|晚间|晚|夜|夜间)`)

	if amReg.MatchString(inputs) {
		flag = 1 // 上午
		inputs = amReg.ReplaceAllString(inputs, "")
	} else if pmReg.MatchString(inputs) {
		flag = 2 // 下午
		inputs = pmReg.ReplaceAllString(inputs, "")
	} else if nightReg.MatchString(inputs) {
		flag = 3 // 晚上
		inputs = nightReg.ReplaceAllString(inputs, "")
	}

	return inputs, flag, nil
}

// 处理月份
// 返回值: 日期, 是否是农历, 是否是闰年, 是否需要加减天数, 是否有错误
func (t *Transform) TransformChineseTimeofMonth(inputs string) (string, bool, bool, int, error) {
	// 处理 昨天/前天/昨日/前日/今天/今日/明天/明日/后天/后日
	jumpDay := 0
	dReg := regexp.MustCompile(`(昨天|前天|昨日|前日|今天|今日|明天|明日|后天|后日)`)
	inputs = dReg.ReplaceAllStringFunc(inputs, func(s string) string {
		loc, _ := time.LoadLocation("Asia/Shanghai")
		m := time.Now().In(loc).Format("01")
		d := time.Now().In(loc).Format("02")

		switch s {
		case "前天", "前日":
			jumpDay = -2
		case "昨天", "昨日":
			jumpDay = -1
		case "明天", "明日":
			jumpDay = 1
		case "后天", "后日":
			jumpDay = 2
		default:
			jumpDay = 0
		}

		s = fmt.Sprintf("%s月%s日", m, d)
		return s
	})

	flag := false     // 是否为农历
	beapFlag := false // 是否为闰月
	ccReg := regexp.MustCompile(`(农历|阴历|初[一二三四五六七八九十]|七夕|元宵|端午|中秋|重阳|中元|春节|闰[一二三四五六七八九十]+月)`)
	if ccReg.MatchString(inputs) {
		flag = true // 农历, 暂时只需要标记, 不需要清空

		// 去掉农历/阴历
		inputs = strings.NewReplacer("农历", "", "阴历", "").Replace(inputs)
	}

	beapReg := regexp.MustCompile(`(闰[一二三四五六七八九十]+月)`)
	if beapReg.MatchString(inputs) {
		beapFlag = true // 农历, 暂时只需要标记, 不需要清空

		// 去掉农历/阴历
		inputs = strings.NewReplacer("闰", "").Replace(inputs)
	}

	// 处理特殊日期, 除夕日期不固定, 需要特殊处理
	inputs = strings.NewReplacer("七夕情人节", "7月7日", "七夕节", "7月7日", "七夕", "7月7日", "七月七日情人节", "7月7日").Replace(inputs)
	inputs = strings.NewReplacer("春节", "1月1日", "元宵节", "1月15日", "五月初五端午节", "5月5日", "端午节", "5月5日", "八月十五中秋节", "8月15日", "中秋节", "8月15日", "九月九日重阳节", "9月9日", "重阳节", "9月9日", "中元节", "7月14日").Replace(inputs)
	inputs = strings.NewReplacer("元宵", "1月15日", "端午", "5月5日", "中秋", "8月15日", "重阳", "9月9日", "中元", "7月14日").Replace(inputs)

	// 其他节日
	// 先把完整的节日名称替换
	inputs = strings.NewReplacer("元旦节", "1月1日", "国庆节", "10月1日", "六一儿童节", "6月1日", "五一劳动节", "5月1日", "五四青年节", "5月4日", "三八妇女节", "3月8日", "教师节", "9月10日", "建军节", "8月1日", "建党节", "7月1日", "情人节", "2月14日").Replace(inputs)
	// 再把节日中的节日简称称替换
	inputs = strings.NewReplacer("元旦", "1月1日", "国庆", "10月1日", "劳动节", "5月1日", "儿童节", "6月1日", "青年节", "5月4日", "妇女节", "3月8日").Replace(inputs)

	// 11月和12月需要比其他月份先处理, 不然1月和2月有可能把11月和12月替换掉了, 而出现错误
	// 处理特殊月份 转换  11月
	NovReg := regexp.MustCompile(`((十一|冬|子|葭|畅|辜|寒)月|(仲|正|中)冬|黄钟)`)
	inputs = NovReg.ReplaceAllString(inputs, "11月")

	// 处理特殊月份 转换  12月
	DecReg := regexp.MustCompile(`((十二|腊|梅|丑|冰|严|涂)月|(季|残|末|暮)冬|大吕|岁杪)`)
	inputs = DecReg.ReplaceAllString(inputs, "12月")

	// 处理特殊月份 转换  1月
	JanReg := regexp.MustCompile(`((正|元|柳|端|陬|嘉|寅|一)月|孟春)`)
	inputs = JanReg.ReplaceAllString(inputs, "1月")

	// 处理特殊月份 转换  2月
	FebReg := regexp.MustCompile(`((二|杏|如|卯|花|酣|丽)月|仲春|仲阳|殷春)`)
	inputs = FebReg.ReplaceAllString(inputs, "2月")

	// 处理特殊月份 转换  3月
	MarReg := regexp.MustCompile(`((三|桃|蚕|绸|桐|莺|辰)月|(暮|晚|余)春)`)
	inputs = MarReg.ReplaceAllString(inputs, "3月")

	// 处理特殊月份 转换  4月
	AprReg := regexp.MustCompile(`((四|麦|槐|余|阳|纯|巳)月|孟夏|首夏|初夏|新夏|中吕|清和)`)
	inputs = AprReg.ReplaceAllString(inputs, "4月")

	// 处理特殊月份 转换  5月
	MayReg := regexp.MustCompile(`((五|蒲|榴|皋|午|超|恶|毒)月|仲夏|中夏|蕤宾|郁蒸)`)
	inputs = MayReg.ReplaceAllString(inputs, "5月")

	// 处理特殊月份 转换  6月
	JunReg := regexp.MustCompile(`((六|荷|伏|暑|焦|末|且|荔|季)月|季夏|晚夏|林钟|暮夏)`)
	inputs = JunReg.ReplaceAllString(inputs, "6月")

	// 处理特殊月份 转换  7月
	JulReg := regexp.MustCompile(`((七|瓜|兰|巧|秋|相|申)月|新秋|兰秋|首秋|初秋|孟秋|肇秋|夷则)`)
	inputs = JulReg.ReplaceAllString(inputs, "7月")

	// 处理特殊月份 转换  8月
	AugReg := regexp.MustCompile(`((八|桂|壮|酉|拓|有)月|仲秋|桂秋|清秋|素商|商秋|商吕|秋半|仲商)`)
	inputs = AugReg.ReplaceAllString(inputs, "8月")

	// 处理特殊月份 转换  9月
	SepReg := regexp.MustCompile(`((九|菊|戌|玄)月|霜序|(深|暮|残|晚|穷|杪)秋)`)
	inputs = SepReg.ReplaceAllString(inputs, "9月")

	// 处理特殊月份 转换  10月
	OctReg := regexp.MustCompile(`((十|亥|阳|露)月|(孟|早|上|初|开|新|首)冬)`)
	inputs = OctReg.ReplaceAllString(inputs, "10月")

	// 在月份中处理日期, 在日期中, 需要处理几月半的情况, 如: 七月半(7月14日), 六月半(6月15日), 二月半(2月14日)等
	monthReg := regexp.MustCompile(`\d+\s*月半`)

	inputs = monthReg.ReplaceAllStringFunc(inputs, func(s string) string {

		// 去掉空白字符
		reg := regexp.MustCompile("\\s+")
		s = reg.ReplaceAllString(s, "")

		// 处理月半情况(7月半特殊处理)
		if strings.Contains(s, "7月半") {
			s = strings.NewReplacer("7月半", "7月14日").Replace(s)
		}

		// 处理月半情况
		s = strings.NewReplacer("月半", "月15日").Replace(s)

		s = t.subUtil(s, "cn2an", "date")
		return s
	})

	dayReg := regexp.MustCompile(`(初[一二三四五六七八九十](日|号)?|[一二三四五六七八九十]+(日|号)?)`)
	inputs = dayReg.ReplaceAllStringFunc(inputs, func(s string) string {
		s = strings.NewReplacer("号", "日", "初", "").Replace(s)

		if !strings.HasSuffix(s, "日") {
			s = s + "日"
		}
		s = t.subUtil(s, "cn2an", "date")
		return s
	})

	return inputs, flag, beapFlag, jumpDay, nil
}

// 处理年
func (t *Transform) TransformChineseTimeofYear(inputs string) (string, error) {
	patternYear1 := regexp.MustCompile(`(今年|去年|前年|明年|后年)`)
	inputs = patternYear1.ReplaceAllStringFunc(inputs, func(s string) string {
		y := time.Now().Year()
		if s == "今年" {
			s = fmt.Sprintf("%d年", y)
		} else if s == "去年" {
			s = fmt.Sprintf("%d年", y-1)
		} else if s == "前年" {
			s = fmt.Sprintf("%d年", y-2)
		} else if s == "明年" {
			s = fmt.Sprintf("%d年", y+1)
		} else if s == "后年" {
			s = fmt.Sprintf("%d年", y+2)
		}
		return s
	})

	patternYear := regexp.MustCompile(fmt.Sprintf(`[%s%s0-9]+\s*年`, t.allNum, t.allUnit))
	inputs = patternYear.ReplaceAllStringFunc(inputs, func(s string) string {
		// 去掉空白字符
		s = removeSpace(s)

		s = t.subUtil(s, "cn2an", "date")
		return s
	})

	return inputs, nil
}

func removeSpace(inputs string) string {
	reg := regexp.MustCompile("\\s+")
	return reg.ReplaceAllString(inputs, "")
}
